/*
 * Drunk Js
 * Author    :   Drunk
 * Website   :   http://drunkce.com,  http://idrunk.net
 */

(function(Drunk){
var $ = Drunk ,	jQuery = Drunk ;
Drunk.about = {
	'Author' : 'Drunk' ,
	'Homepage' : 'http://idrunk.net/' ,
	'version' : '1.0.1'
} ;
Drunk.local = ownPath() ;
Drunk.extend(Drunk.local, {
	'extpath' : Drunk.local.dir + 'extends/' ,
	'plugpath' : Drunk.local.dir + 'plugins/'
}) ;

var userAgent = navigator.userAgent ,
	location = document.location ,
	rwebkit = /(webkit)[ \/]([\w.]+)/,
	ropera = /(opera)(?:.*version)?[ \/]((\d+)[\.\d]+)/,
	rmsie = /(msie) ((\d+)[\.\d]+)/,
	rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/ ,

	rfirefox = /\b(firefox)\/((\d+)[\.\d]+)/ ,
	rmaxthon = /\b(maxthon)\/((\d+)[\.\d]+)/ ,
	rchrome = /\b(chrome)\/((\d+)[\.\d]+)/ ,
	rsafari = /\bversion\/((\d+)[\.\d]+).*\b(safari)\b/ ;

Drunk.fn.extend({
	// 判断或设置某元素是否可选中
	contentSelect : function(boolean){
		var me = Drunk($.browser.mozilla && this[0] === document ? document.body : this[0]) ;
		if(Drunk.isUndef(boolean)){
			$.browser.mozilla ? (me.css("-moz-user-select") === "none" ? false : true) : !me[0].onselectstart || me[0].onselectstart()
		}else{
			if($.browser.mozilla)return me.css("-moz-user-select", boolean ? "all" : "none") ;
			me.each(function(index, element){
				element.onselectstart = function(){return boolean ;}
			}) ;
		}
		return me;
	} ,

	// 克隆元素属性	status:{1:return, 4:removeOldAttr}
	attrClone : function(elem, status){
		var me = this , i = 0 ,
			attrs = ['drunk', 'class','style', 'onclick','onmouseover','onmouseout','onkeydown','onkeyup','onkeypress','onchange','onfocus','onblur', 'disabled','selected','checked','autocomplete'] ;

		if($.isPlainObject(elem)){
			for(i in elem)me.attr(i, elem[i]) ;
			return me ;
		}

		elem = $(elem) ;
		attrsMem = {} ;
		for(;i<attrs.length;i++){
			if(Drunk.isUndef(me.attr(attrs[i])))continue ;
			if(!(status & 1))elem.attr(attrs[i], me.attr(attrs[i])) ;
			// 记录属性
			attrsMem[attrs[i]] = me.attr(attrs[i]) ;
			if(status & 4)me.removeAttr(attrs[i]) ;
		}

		return (status & 1) ? attrsMem : me ;
	} ,
	
	traversal : function(nodeType, callback){
		root = this.length ? this : Drunk(document.body) ;
		nodeType = nodeType || 1 ;
		var currentNode , inCall , jCurrentNode ;
		
		inCall = function(currentNode){
			jCurrentNode = $(currentNode) ;
			if(currentNode.nodeType == 1)jCurrentNode.traversal(nodeType, callback) ;
			if(currentNode.nodeType == nodeType){
				if(typeof callback == "function")callback(currentNode) ;
			}
		}
	
		root.each(function(i,e){
			if(e.hasChildNodes()){
				currentNode = e.firstChild ;
				oldNode = currentNode ;
				while((currentNode = currentNode.nextSibling) !== null){
					inCall(oldNode) ;
					oldNode = currentNode ;
				}
				inCall(oldNode) ;
			}
		}) ;
	}
}) ;

Drunk.extend({
	Cache : {} ,
	
	// 返回所有相关的客户端尺寸信息
	clientSize : function(){
		var	body = document.body ,
			size = [screen.availWidth ,screen.availHeight ,
				document.documentElement.clientWidth ,document.documentElement.clientHeight ,
				body.offsetWidth, body.offsetHeight ,
				body.scrollWidth, body.scrollHeight
			]

		return {
			screen : {width : size[0], height : size[1]} ,
			window : {width : size[2], height : size[3]} ,
			body : {width : size[4], height : size[5] ,
				widths : size[6] < size[2] ? size[2] : size[6] , heights : size[7] < size[3] ? size[3] : size[7]
			}
		} ;
	} ,

	clientPos : function(){
		var body = document.body , documentElement = document.documentElement ;
		return {x: body.scrollLeft || documentElement.scrollLeft , y : body.scrollTop || documentElement.scrollTop} ;
	} ,

	// 判断触发事件时是不是对应的绑定元素触发的
	isTriggered : function(element){
		var event = Drunk.currentEvent() ;
		if(!event)return false ;
		var target = event.relatedTarget || (event.type === "mouseover" ? event.fromElement : event.toElement) ;
		return !Drunk.isContain(element, target) ;
	} ,

	objParse : function(object){
		try{
			eval("var variable = "+object) ;
		}catch(err){
			var variable = null ;
		}
		return variable ;
	} ,


    int : function(object){ return Drunk.isNum(object) ? parseInt(object) : (object === true ? 1 : 0);} ,

    float : function(object){ return Drunk.isNum(object) ? parseFloat(object) : (object === true ? 1 : 0);} ,

	isNum : function(object){ return !isNaN(parseFloat(object)) && isFinite(object) ;} ,

	isInt : function(object){ return !isNaN(parseInt(object)) && isFinite(object) ;} ,

	isFunc : function(object){ return typeof object === "function" ;} ,

	isStr : function(object){ return typeof object === "string" ;} ,

	isObj : function(object){ return typeof object === "object" ;} ,

	isUsefulObj : function(object){ return object && typeof object !== "boolean" && Drunk.isObj(object) ;} ,

	isUndef : function(object){ return typeof object === "undefined" ;} ,

	empty : function(object){return !object || object === '0' || (Drunk.isObj(object) && $.isEmptyObject(object)) || ($.isArray(object) && !object.length) ;} ,

	isReg : function(object){ return Object.prototype.toString.call(object) === "[object RegExp]"} ,

	// method > 0 : 返回是否网页元素, method & 2 返回是否jquery对象
	isElem : function(object, tag, method){
		if(!object || !Drunk.isObj(object))return false ;
		var domtype = object.nodeType === 1 ? 1 : (object instanceof jQuery || object['jquery'] ? 2 : 0);
		if(method || !tag)return (method & 2) ? domtype === 2 : !!domtype;
		return domtype === 1 ? Drunk.isStr(tag) && object.tagName.toLowerCase() === tag.toLowerCase() : false ;
	} ,

	imgReady : function(image){return Drunk.ie ? image.readyState == "complete" : image.complete} ,

	currentEvent : function(){
		if(window.event)return window.event ;
		var caller = arguments.callee , i = 0, cycle = 16;
		for(;i<cycle;i++)if((caller = caller.caller) && caller.arguments.length && caller.arguments[0].relatedTarget)return caller.arguments[0] ;
	} ,

	eventTarget : function(evt){evt = evt || Drunk.currentEvent() ;return Drunk.browser.msie ? evt.srcElement : evt.target ;} ,

	isContain : function(parent, child){
		if (parent.contains)return parent === child || parent.contains(child) ;
		if (parent.compareDocumentPosition)return parent === child || parent.compareDocumentPosition(child) & 16;
	} ,

	// 按下的按键是否字符输出按键
	isValkey : function(keyCode){
		// 判断是否退格/制表/空格/删除键,是否字母数字键,是否符号键
		return Drunk.isInt(keyCode) && (keyCode == 8 || keyCode == 9 || keyCode == 32 || keyCode == 46 || 
			(keyCode > 64 && keyCode < 91) || (keyCode > 47 && keyCode < 58) || (keyCode != 108 && keyCode > 95 && keyCode < 112) || (keyCode > 185 && keyCode < 193) || (keyCode > 218 && keyCode < 223)) ;
	} ,

	ifnull : function(isnull, returnVal){
		return isnull === null || isnull === undefined ? returnVal : isnull ;
	} ,

	ifempty : function(isempty, returnVal){
		return Drunk.empty(isempty) ? returnVal : isempty ;
	} ,

	// 模拟表单提交数据
	submit : function(url,data,bit){
		bit = Drunk.int(bit);
		var target = bit & 1 ? ' target="_blank"' : '';
		if(!$.isPlainObject(data))return $('<a '+target+'>').attr('href', url).appendTo(document.body).get(0).click();
		var hidden , x, form = $('<form method="POST" '+target+' action="'+url+'" style="display:none;">').appendTo(document.body);
		for(k in data)$('<input type="hidden" name="' +k+ '" />').val(data[k]).appendTo(form) ;
		form.trigger('submit') ;
	} ,
	
	// 位元判断拆分组合
	// method:{0:返回位元拆解元值数组, 1:合并位元原值数组, 16:判断是否位元元值, 32:返回拆解的首位位元元值}
	bit : function(bit, method, map){
		var i = 0, analysis = 0 ;
		if(!$.isArray(map))map = [1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912] ;

		if(method & 1){
			if(!$.isArray(bit))bit = Drunk.bit(bit, 0, map) ;
			for(;i<bit.length;i++)analysis = analysis | bit[i] ;
		}else if(method & 16){
			bit = Drunk.int(bit) || -1 ;
			analysis = ! (bit & (bit - 1)) ;
		}else{
			if($.isArray(bit))bit = Drunk.bit(bit, 1, map) ;
			bit = Drunk.int(bit) ;
			analysis = [] ;

			for(;i<map.length;i++)if((bit & map[i]) === map[i]){analysis[analysis.length] = map[i];if(method & 32)return map[i];else if(method & 64)return i;}
		}

		return analysis ;
	} ,

	// 反解析对象,返回对象内容的Json形式字符串
	dump : function(object, maxLevel, method, level){
		var i = 0, name, value, term, array = [], quot , overflow , space, bodySpace, footSpace;

		if(!Drunk.isNum(level))level = 0 ;
		level ++ ;
		// 如果指定了解析的最大递归级数,则判断是否溢出
		if(maxLevel > 0)overflow = level > maxLevel ;

		space = method & 2 ? '    ' : '	' ;
		footSpace = method & 1 ? '\r\n' + space.repeat(level-1) : '' ;
		bodySpace = method & 1 ? footSpace + space : '' ;
		// 如果对象是数组则递归
		if($.isArray(object)){
			for(;i<object.length;i++)array[i] = Drunk.dump(object[i], maxLevel, method, level) ;
			return "[" + bodySpace + array.join("," + bodySpace) + footSpace + "]" ;
		}
		
		// 如果解析的对象不是一个有效的对象或者已经溢出,则当作字符串处理,并编码
		if(!D.isUsefulObj(object) || overflow){
			quot = '"' ;
			// 进行php的json_encode形式编码,方便php解析
			return quot + String(object).safechar().convert() + quot ;
		}

		for(name in object){
			value = object[name];
			term = '"' + String(name).safechar().convert() + '":' ;
			// 如果该值为有效对象,则递归
			if($.isArray(value) || D.isUsefulObj(value)){
				term += Drunk.dump(value, maxLevel, method, level) ;
			}else{
				quot = '"' ;
				term += quot + String(value).safechar().convert() + quot ;
			}
			array[array.length] = term;
		}
		return "{" + bodySpace + array.join("," + bodySpace) + footSpace + "}";
	} ,
	
	first : function(object, filter){
		if(typeof object !== 'object')return false ;
		for(i in object){
			if(filter && Drunk.isReg(filter) && !filter.test(i))continue ;
			return object[i] ;
		}
		return null ;
	} ,

	// 搜索数组或对象,无限级深度搜索,返回下标或匹配到的数组,可用正则对比或者直接比较,如果有定义count,则当对象为对象时,附加一个length属性
	objSearch : function(object, value, column, matchall, count){
		// 判断object是数组还是有效对象
		var isArray = $.isArray(object) || (Drunk.isUsefulObj(object) ? false : null) ;
		// 如果对象不是数组或者有效对象,则返回-1
		if(isArray === null)return -1 ;

		// 搜索值是否正则表达式
		var	isReg = Drunk.isReg(value) ,
			i , index = 0 , result , length = 0 ,
			// 获取搜索的深度,如果不是数组则表示直接搜索第一层
			width = $.isArray(column) ? column.length : 0 ,
			// 是否返回匹配成功的索引的其他子项
			children = $.isArray(matchall) ? matchall.length : 0 ,
			// 如果matchall有值,如果是数组,或者要返回匹配的子项,则初始化为数组,或者初始化为对象,否则初始化为-1
			group = matchall ? (isArray || children ? [] : {}) : -1 ,
			// 多层搜索递归
			recursive = function(object, level, width, index){
				// 如果深度不够则递归,如果够了或者没有下级则返回对应值或者undefined
				return index < width - 1 && !Drunk.isUndef(object[level[index]]) ? 
					recursive(object[level[index]], level, width, index + 1) : object[level[index]] ;
			} ;
		
		for(i in object){
			// 如果搜索的是数组并且该值的键值不是数字则过滤掉,或者如果要搜索下层并且层数不够则跳过
			if(isArray && !Drunk.isInt(i) || width && Drunk.isUndef(result= recursive(object[i],column,width,index)))continue ;
			// 如果搜索下层,如果是正则搜索到或者直接对比相同,或者首层匹配到.如果是判断是否存在则返回下标,否则存入group,完毕后返回
			if(width ? (isReg ? value.test(result) : result == value) : (isReg ? value.test(object[i]) : object[i] == value)){
				if(!matchall)return i ;
				length ++ ;
				if(children){
					group.push(recursive(object[i], matchall, children, index)) ;
				}else{
					isArray ? group.push(object[i]) : group[i] = object[i] ;
				}
			}
		}
		// 如果对象是对象,并且要返回长度,则赋予length属性
		if(!isArray && count)group.length = length ;
		return group ;
	} ,
	loadScript : function(url, data, callback) {
		var head = document.getElementsByTagName('head')[0] || document.body,
			script = document.createElement('script');
		head.appendChild(script);
		script.src = url;
		script.charset = 'utf-8';
		script.onload = script.onreadystatechange = function() {
			if (!this.readyState || this.readyState === 'complete' || this.readyState === 'loaded') {
				if(Drunk.isFunc(callback))Drunk(function(){callback(data)});
				script.onload = script.onreadystatechange = null;
			}
		};
	} ,
	// 对象转数组
	objarray : function(object, key){
		if(!Drunk.isUsefulObj(object) || Drunk.empty(object))return false ;
		var array = [] , i ;
		for(i in object)array[array.length] = key ? i : object[i] ;
		return array ;
	} ,
	// 强转对象
	objObj : function(obj, keys, emptyString){
		var i=0 , object = {} ;
		emptyString = emptyString ? '' : undefined ;
		
		if(Drunk.isUndef(keys))return obj ;
		if(!$.isArray(keys))keys = [String(keys)] ;
		if(!$.isPlainObject(obj)){
			if(!$.isArray(obj))obj = [obj] ;
			for(;i<keys.length;i++){object[keys[i]] = typeof obj[i] === 'undefined' ? emptyString : obj[i] ;}
			return object ;
		}
		
		for(;i<keys.length;i++)object[keys[i]] = typeof obj[keys[i]] === 'undefined' ? emptyString : obj[keys[i]] ;
		return object ;
	} ,
	
	// 存取Cookie, 兼容PHP可以存数组
	cookie : function(key,value,expires,path,host){
		var isGet = Drunk.isUndef(value) ,
			group = {} ,
			matches , follow , slash ;
	
		key = Drunk.cookiePrefix ? Drunk.cookiePrefix + key : key ;
		// 解析Cookie健, 以供后面的二次正则
		key = key.replace(/^(.+?)(\[([^\[\]]+)\])?$/,function($0,$1,$2,$3){
			slash = isGet ? "\\" : "" ;
			return $2 ? encodeURIComponent($1)+slash+"["+encodeURIComponent($3)+slash+"]" : encodeURIComponent($1) ;
		}) ;
	
		// 判断是取Cookie还是存Cookie
		if(isGet){
			matches = document.cookie.Match(new RegExp("(^|[;\\s])"+key+"(\\[([^\\[\\]]+)\\])?=([^;]+)","gi")) ;
			if(!matches.length)return undefined ;
			// 如果匹配个数为1, 并且第二分组没有匹配到内容, 则表示成功匹配到该Cookie, 并且其职为字符串
			if(1 == matches.length && !matches[0][2])return decodeURIComponent(matches[0][4]) ;
			for(var i=0;i<matches.length;i++){
				if(!matches[i][3])continue ;
				// 将匹配到的元素压入Json
				group[decodeURIComponent(matches[i][3])] = decodeURIComponent(matches[i][4]) ;
			}
			return group ;
		}else{
			follow = (expires ? ";expires=" + new Date(Drunk.time(0,1)+86400000*expires).toGMTString() : "") +
				(path ? ";path=" + path : "") ;
			// 判断要储存的是对象还是字符串
			if($.isPlainObject(value)){
				for(i in value){
					document.cookie = key +"[" +encodeURIComponent(i)+ "]" + "=" + encodeURIComponent(value[i]) + follow ;
				}
			}else{
				return document.cookie = key + "=" + encodeURIComponent(value) + follow ;
			}
		}
	} ,
	
	browser : {} ,
	uaMatch: function( ua ) {
		ua = ua.toLowerCase();

		var match = rwebkit.exec( ua ) ||
				ropera.exec( ua ) ||
				rmsie.exec( ua ) ||
				ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || [] ,
			match2 = rfirefox.exec(ua) ||
				rmaxthon.exec(ua) ||
				rchrome.exec(ua) ||
				rsafari.exec(ua) ||
				match.slice() || [] ;

		if(match2[1] === 'msie'){
			match2[1] = 'ie'
		}else if(match2[3] && match2[3] === 'safari'){
			match2[3] = match2[2];match2[2] = match2[1];match2[1] = 'safari';
		}
		return { browser: match[1] || "", version: match[2] || "0", name: match2[1] || '', ver: match2[3] || "0", version2: match2[2] || "0" };
	}
}) ;

var browserMatch = Drunk.uaMatch( userAgent );
if ( browserMatch.browser ) {
	Drunk.browser[ browserMatch.browser ] = true;
	Drunk.browser.version = browserMatch.version;
	Drunk.browser.kernel = browserMatch.browser;
	Drunk.browser.name = browserMatch.name;
	Drunk.browser.ver = browserMatch.ver;
	Drunk.browser.version2 = browserMatch.version2;
	if ( Drunk.browser.webkit )Drunk.browser.safari = true;
}

Drunk.extend({
	winResizeCall : (function(){
		var callbacks = $.Callbacks() ;
		$(window).bind("resize", function(evt){
			Drunk.winResizeCall.fire(evt) ;
		}) ;
		return callbacks ;
	})()
}) ;



window.D = window.Drunk = Drunk ;




// -------------------------------------------- Prototype扩展部分 -------------------------------------------- \\

String.prototype.regfilter = function(){
	return this.replace(/([\^\$\(\)\[\]\{\}\.\*\+\?\\\|])/g, '\\$1') ;
}

// 字符串基本扩展
// 填充字符串,常用于数字前面补零
String.prototype.summary = function($start, $length, $ellipsis, $bit){
    $content = this;
    $start = D.int($start);
    $length = D.int($length);
    if(!$ellipsis) $ellipsis = '...';
    if(!$bit) $bit = 0;
    $content = $content.replace(/^(\s|&nbsp;)+|(\s|&nbsp;)+$/i, '', $content.replace(/\s+/i, ' ', $content.striptags()));
    $content_len = $content.length;
    if(!$length){
        $length = $start;
        $start = 0;
    }
    if(!$length) $length = $content_len;
    if($length >= $content_len) $ellipsis = '';

    if($bit & 1){
        $return = $content.substr(0, $start) + $ellipsis + $content.substr($start + $length, $content_len);
    }else{
        $return = $content.substr($start, $length) + $ellipsis;
    }
    return $return;
}

// 字符串基本扩展
// 填充字符串,常用于数字前面补零
String.prototype.fill = function(length, fill, to){
	fill = fill ? String(fill) : "0" ;
	var less = length - this.length ,
		str = this ,
		i = 0;
	for(;i<less;i++)str = to ? str + fill : fill + str ;
	return str ;
}

// 返回字符串所占字节数
String.prototype.byte = function(ratio){
	ratio = ratio || 3 ;
	var match = this.Match(/[^\x00-\xff]/g) ;
	return this.length + (match ? match.length : 0) * (ratio - 1)
}

// 去掉头尾指定字符串
String.prototype.trim = function(place, sign){
	sign = Drunk.isUndef(sign) ? '\\s' : sign ;
	place = new RegExp(place ? (place == 1 ? '^('+sign+')+' : (place == 2 ? '('+sign+')+$' : '('+sign+')+')) : '^('+sign+')+|('+sign+')+$', 'g') ;
	return this.replace(place, '') ;
}

String.prototype.striptags = function(){
	var reg = /<!--[\s\S]+?-->|<(script|style)\b[\s\S]+?<\/\1>|<[^>]+>/gi ;
	return this.replace(reg, '') ;
}

String.prototype.ucfirst = function(){	return this.substr(0,1).toUpperCase() + this.substr(1) ;}

// 重构match方法, 如果有指定index则返回该索引的分组的数组
String.prototype.Match = function(reg, index){
	var matches , group = [] , i = 0 ;
	matches = this.match(reg) || [] ;
	if(!isNaN(index) && index !== "" && index !== null){
		for( ;i<matches.length;i++)group[i] = new RegExp(reg).exec(matches[i])[index] ;
	}else{
		for( ;i<matches.length;i++)group[i] = new RegExp(reg).exec(matches[i]) ;
	}
	return group ;
}

// 字符串转码{mode:{1:解码,0:编码} , prefix : 转换的前缀形式}
String.prototype.convert = function(mode, prefix){
	prefix = String(prefix || "\\u") ;
	if(mode){
		str = unescape(this.replace(new RegExp(prefix,"g"), "%u")) ;
	}else{
		// 替换双字节字符后返回
		return this.replace(/([\u0255-\uffff])/g, function($0, $1){
			return prefix + $1.charCodeAt().toString(16) ;}
		) ;
	}
}

// Url形式字符串参数读写,兼容PHP可以设置PHP数组形式键,如key[].没有指定val的话则执行url取参,匹配到多个返回数组,单个返回对应值
String.prototype.urlQuery = function(key, val, array){
	// 解析url参数
	if(Drunk.isUndef(key)){
		//var reg = 
	}
	// 将特殊正则字串转义
	var keyReg = key.regfilter() , connector , reg , matches ;
	// 正则搜索参数健
	reg = new RegExp("(\\?" + keyReg + "=|&" + keyReg + "=)([^&#]*)","gi") ;
	// 判断是取值还是赋值
	if(Drunk.isUndef(val)){
		matches = this.Match(reg, 2) ;
		return matches.length > 1 ? matches : (matches.length == 1 ? matches[0] : undefined) ;
	}else{
		// 搜索该键是否存在,执行对应赋参工作
		connector = this.search(/\?/) == -1 ? "?" : "&" ;
		return this.search(reg) == -1 ? (
			this + connector + key + "=" + val
		) : (
			array ? this + connector + key + "=" + val  : this.replace(reg, function($0, $1, $2){
				if(val !== null)return $1 + val ;
				return $1.substr(0,1) === "?" ? '?' : '' ;
			})
		) ;
	}
};

String.prototype.url = function(key, value){
	var uri = this , uriParse , i ;
//		reg = /(https?|ftp|file):\/{2,3}(([a-z\d]+[a-z\d-]*\.)*\w+)(:\d*)?((\/([\w%.]+\/)*)(([\w%.]+?)(\.([\w%]+))?)?)?(((\?|&+)[\w%]+=?[\w%\/@]*)*)(#([\w%\/.+=_&@]*))?($|[\s"'])/i ;		怎么用还有待研究
		map = {'protocol':1, 'host':2, 'port':5, 'path':6, 'search':9, 'hash':11} ,
		reg = /(https?|ftp|file):\/{2,3}(([a-z\d]+[a-z\d-]*\.)*\w+)(:(\d*))?(\/([\w%.]+\/)*[\w%.-]*)?(\?([\w%\/@&=-]*))?(#([\w%\/.+=_&@]*))?$/i ;

	if(!Drunk.isUndef(map[key]) && !Drunk.isUndef(value)){
		uriParse = uri.url() ;
		if(!uriParse)return '' ;
		uriParse[key] = value ;
		if(!Drunk.empty(uriParse['protocol']))uriParse['protocol'] += uriParse['protocol'] === 'file' ? ':///' : '://' ;
		if(!Drunk.empty(uriParse['port']))uriParse['port'] = uriParse['port'] == 80 ? '' : ':' + uriParse['port'] ;
		if(!Drunk.empty(uriParse['search']))uriParse['search'] = '?' + uriParse['search'] ;
		if(!Drunk.empty(uriParse['hash']))uriParse['hash'] = '#' + uriParse['hash'] ;
		return String(Drunk.objarray(uriParse).join('')) ;
	}else if(!Drunk.isUndef(map[key])){
		uriParse = uri.match(reg) ;
		if(!uriParse)return '' ;
		return String(uriParse[map[key]] || (key === 'port' ? 80 : '')) ;
	}else{
		uriParse = uri.match(reg)
		if(!uriParse)return '' ;
		var obj = {} ;
		
		for(i in map){obj[i] = uriParse[map[i]] || (i === 'port' ? 80 : '') ;}
		return obj ;
	}
}

String.prototype.roothost = function(){
	var url = this ;
	if(url == '')url = location.href ;
	var urlParse = url.url() ;
	if(Drunk.isInt(urlParse['host'].substr(-1)))return urlParse['host'] ;
	var suffixMapReg = /[a-z]+(?:\.(?:com|net|cn|gov|edu|co|cm|us|uk))?\.[a-z]+$/i ;
	var roothost = urlParse['host'].match(suffixMapReg) ;
	return roothost ? roothost[0] : urlParse['host'] ;
}

String.prototype.path = function(extension){
	var path = this , pathParse,
		map = {'dir':1, 'file':3, 'filename':4, 'extension':5} ,
		reg = /^(\/?([^\\\/:*?"<>|]*\/)*)(([^\\\/:*?"<>|]*)\.(\w+))$/i ;

	if(!Drunk.isUndef(extension)){
		pathParse = path.match(reg) ;
		if(!pathParse)return '' ;
		return String(pathParse[map[extension]] || '') ;
	}else{
		pathParse = path.match(reg) ;
		if(!pathParse)return '' ;
		var obj = {} ;
		
		for(i in map){obj[i] = uriParse[map[i]] || '' ;}
		return obj ;
	}
}


// 字符串形式数组操作
// 字符串数组插入元素
String.prototype.arrayInsert = function(child, index){
	eval("var array = "+this) ;
	if(!jQuery.isArray(array))return false ;
	index = !index || isNaN(index) || index < 0 ? 0 : index ;
	array.splice(index, 0, child) ;
	return Drunk.dump(array) ;
}

// 字符串数组删除元素
String.prototype.arrayDelete = function(child, length, isIndex){
	eval("var array = "+this) ;
	if(!jQuery.isArray(array))return false ;
	return Drunk.dump(array.remove(child, length, isIndex)) ;
}

String.prototype.Split = function(expression){
	if(typeof expression == "string")return this.split(expression) ;
	return this.replace(expression, "::split::").split("::split::") ;
}

// 提取字符串结构字符串
String.prototype.separate = function(){
	var object = this ,
		parts = [] , 
		i = 0 , j = 0 , 
		quotationReg = /^'|"$/i ,
		currentChar , 
		string = "" , 
		quotationOpen = false ,
		quotationMark = "#`QUOTATION" ,
		partMark = "#`PART" ,
		markClose = "#" ,
		quotationIndex ;

	for(;i<object.length;i++){
		currentChar = object.substr(i, 1) ;
		// 如果不是引号,则节录分段,并跳过
		if(!quotationReg.test(currentChar)){
			// 如果字符串段开关已开,则记录字符段,否则正常记录字符串
			if(quotationOpen){
				parts[j] += currentChar ;
			}else{
				string += currentChar ;
			}
			continue ;
		// 如果该引号为字符串中引号,即其前面有反斜杠转义符,则删掉该转义符并拼接字符
		}else if(i && object.substr(i - 1,1) == '\\'){
			quotationIndex = quotationMark === "'" ? 0 : 1 ;
			if(quotationOpen){
				parts[j] = parts[j].slice(0,-1) + quotationMark + quotationIndex + markClose ;
			}else{
				string = string.slice(0,-1) + quotationMark + quotationIndex + markClose ;
			}
			continue ;
		}

		// 如果字符串段数小于记数,则开启记录开关
		if(parts.length <= j){
			parts[j] = '' ;
			string += partMark + j + markClose ;
			quotationOpen = true ;
			continue ;
		}

		// 关闭记录开关
		quotationOpen = false ;
		j ++ ;
	}
	
	return {'string' : string, 'parts' : parts, 'quotationMark' : quotationMark, 'partMark' : partMark, 'markClose' : markClose} ;
}

// 安全字符过滤
String.prototype.safechar = function(model){
	model = model || 'json' ;
	var backslash = function(string, char){
			char = char || '"' ;
			var chars = char.split('').unique() , i = 0;

			for(;i<chars.length;i++){
				string = string.replace(new RegExp('\\\\*' + chars[i], 'g'), function($0){
					return $0.length % 2 ? '\\' + $0 : $0 ;
				}) ;
			}
			return string ;
		} , 
		safefuncs = {
			'json' : backslash
		} ;

	return String(safefuncs[model](this)) ;
}

String.prototype.spechar = function(attr){
	var url_depr, url_user_depr, map, key,
		string = this ;

	attr = attr || 1 ;
	url_depr = '-' ;
	url_user_depr = '~' ;
	map = {
		"1" : [['\'' , '&sq;'], ['"' , '\\\'']] ,
		"2" : [[url_depr , '*2d'], [url_user_depr , '*7e']] ,
		'4' : [['&','&amp;'],['<','&lt;'],['>','&gt;'],['"','&quot;'],['\'','&#039;']]
	} ;
	key = Drunk.bit(attr, 32) ;
	for(i=0; i<map[key].length; i++)string = attr&16 ? string.replace(new RegExp(map[key][i][1], 'g'), map[key][i][0]) : string.replace(new RegExp(map[key][i][0], 'g'), map[key][i][1]) ;

	return string ;
}

String.prototype.repeat = function(count, glue){
	glue = glue || '' ;
	count = count || 0 ;
	var array = [] , i = 0 ;
	for(;i<count;i++)array[array.length] = this ;
	return array.join(glue) ;
}


// 数组扩展
// 移除数组中重复值元素, 如果指定了column参数并且该参数为大于0的正整数, 则尝试从子数组的column列对比移除重复值元素
Array.prototype.unique = function(column){
	var object = {} , index = this.length-1 , name , object2 = {} , clone = this.slice(0) ,
		isChildSearch = (Drunk.isInt(column) && column > -1) || false ;

	if(isChildSearch){
		// 搜索临时Obj的key, 如果当前数组元素在其key中不存在, 则存入. 如[1,2,2],则最终obj为{"1":0,"2":1}
		for( ; index > -1; index--)
			if(Drunk.isUndef(object2[this[index][column]])){object[this[index]] = index ; object2[this[index][column]] = 1 ;} ;
	}else{
		for( ; index > -1; index--)if(Drunk.isUndef(object[this[index]]))object[this[index]] = index;
	}
	this.length = 0;
	for(val in object)this[this.length] = clone[object[val]] ;
	return this ;
}

// 在数组中搜索给定的值,返回其下标或者匹配到的元素
Array.prototype.search = function(value, column, matches){return Drunk.objSearch(this, value, column, matches) ;}

Array.prototype.remove = function(child,length,isIndex){
	length = length || 1 ;
	if(!isIndex)child = this.search(child) ;
	if(isNaN(child) || child<0)return false ;
	this.splice(child,length) ;
}

Array.prototype.Join = function(glue, model, replaceCall){
	model = model || '[###R]';
	glue = glue || ',';
	var array = this ,
		replace = '\\[###R\\]',
		i = 0 , current;

	for(;i < array.length; i++){
		// 模型赋值
		current = model.replace(new RegExp(replace, 'g'), array[i]);
		array[i] = $.isFunction(replaceCall) ? replaceCall(current) : current;
	}

	return array.join(glue);
}

})(/#.*?noConflict\b/i.test(ownPath().src) ? jQuery.noConflict(true) : jQuery);

function ownPath(){
	var obj = {} ;
	if(jQuery.isReady || !document.scripts.length)return obj ;
	obj.src = document.scripts[document.scripts.length-1].src ;
	obj.path = obj.src.replace(/:\/{2,}/,'').replace(/^[^/]+/, '') ;
	obj.host = obj.src.replace(obj.path, '') ;
	obj.dir = obj.host + obj.path.replace(/[^/]+$/,'') ;
	obj.pathdir = obj.path.replace(/[^/]+$/,'') ;
	return obj ;
}

// 调试窗口, 输出字符串式对象
// 若第一个参数为;+位元数, 则{1:可用第二个参数指定对象输出深度, 2:设置窗口标题, 4:若已有调试框出现,则不再显示, 8:使用alert弹出}
function test(){
	var i, paras, firstPara, additional, parasLength, dwin , dwwidth, dwheight, text, rect, level, title, content ;
	i = 0;
	level = 0;
	title = "Drunk调试窗";
	paras = Array.prototype.slice.call(arguments, 0);
	parasLength = paras.length;

	if(parasLength > 1){
		firstPara = paras[0] ;
		if(typeof firstPara === 'string' && /^;\d+$/.test(firstPara) && paras.shift()){
			additional = firstPara.substr(1) ;
			if(additional & 1 && parasLength > 2 && paras[0] > 0)level = paras.shift() ;
			if((level && parasLength > 3 || !level && parasLength > 2) && additional & 2 && Drunk.isStr(paras[0]))title = paras.shift() ;
		}
	}
	if(additional & 4 && typeof DRUNK_DEBUGING !== 'undefined')return ;
    var isConsole = console && !(additional & 16);

	dwwidth = 800 ;
	dwheight = 500 ;

	if(!isConsole) for(;i<paras.length;i++){
		content = Drunk.dump(paras[i], level, additional & 8 ? 3 : 1) ;
		if(!(additional & 8))content = content.spechar(4) ;
		paras[i] = '[' +i+ ']=>	' + content ;
	}
	text = paras.join('\r\n');

	if(additional & 8)return alert(text);
    if(isConsole){
        console.log(text);
    }else{
        dwin = window.open("","_blank","scrollbars=1,resizable=1,toolbar=0,location=0,directories=0,status=0,menubar=0,width="+dwwidth+",height="+dwheight+',left='+(window.screen.width-dwwidth)/2+',top='+(window.screen.height-dwheight)/2);
        dwin.document.write('<html><head><title>'+title+'</title></head><body style="margin:0;"><pre contenteditable="true">'+text+'</pre></body></html>');
    }
	window.DRUNK_DEBUGING = true ;
}

Drunk.extend({
    /**
     * 记录/判断是否记录
     * @param sign          记录值
     * @param expire        为非null的空时表示取值, 为-1时表取记录集, 为null时表示设置无时限cookie记录, 为非空数时表示设置时限cookie记录
     * @param mother        识别标识
     * @returns {boolean}
     */
	cookied : function(sign, expire, mother){
		var _expire = expire, data ;
		mother = mother || 'signcache' ;
		if(expire !== null) expire = expire || 1 ;
		glue = '-' ;
		
		data = Drunk.cookie(mother, undefined, 0, '/');
        if(D.empty(data))data = "" ;
        if(_expire === -1) return data.match(new RegExp('[^' +glue+ ']+', 'g')) || [];
		if(new RegExp('(?:^|'+glue+')' +sign+ '(?:'+glue+'|$)').test(data))return true ;
		if(!_expire && _expire !== null)return false ;
		data += glue + sign ;
		Drunk.cookie(mother, data, expire, '/') ;
	} ,

	// extends native
	extive : function(){
		if(!arguments.length)return false ;
		var i = 1,
			fun = arguments[0] ,
			args = [] ,
			value = undefined ;
	
		for(;i<arguments.length;i++){args.push("arguments["+ i +"]") ;}
		try{value = eval("external." + fun + "(" + args.join(",") + ")");}catch(e){} ;
	
		return value ;
	} ,
	
	hotkey : function(elem, bubble){
		var start = Drunk.isElem(elem,0,1) || typeof elem === 'boolean' && (bubble = elem) || typeof bubble === 'boolean' ? (Drunk.isElem(elem,0,1) && typeof bubble === 'boolean' ? 2 : 1) : 0 ,
			config = arguments[start] ? (!$.isPlainObject(arguments[start]) ? {} : arguments[start]) : {"116" : false, "17+78" :false} ,
			i = start ,
			keys_analyze , keys_mustdown = {} , hotkeys = {} , hotkey ,
			ele = Drunk.isElem(elem,0,1) ? elem : document ;
			isBubble = typeof bubble === 'boolean' ? bubble : false ;

		// 如果参数一不是以对象形式输入的,则以传入的参数为条件,将其转换为对象
		if($.isArray(arguments[start])){
			for(;i<arguments[start].length;i++){config[arguments[start][i]] = arguments[start + 1] ;}
		// 如果参数一不是有效对象(如果参数个数为基数则添加一个参数)
		}else if(!$.isPlainObject(arguments[start]) && (!(arguments.length % 2 || start % 2) || false === (arguments[arguments.length] = false))){
			for(;i<arguments.length;i+=2){config[String(arguments[i])] = arguments[i+1] ;}
		}

		for(i in config){
			keys_analyze = String(i).Split(/\+/g) ;
			var j=0 , keys_analyze_count = keys_analyze.length, key = keys_analyze[keys_analyze_count - 1] ;
			
			hotkeys[key] = keys_analyze_count > 1 ? {} : 0 ;
			
			for(;j<keys_analyze_count - 1;j++){
				// 如果有状态热键并且未定义,则定义
				if(!$.isPlainObject(keys_mustdown[keys_analyze[j]]))keys_mustdown[keys_analyze[j]] = {"down":false} ;
				// 形如{17:{down:false,78:function(){}}}
				keys_mustdown[keys_analyze[j]][key] = j === keys_analyze_count - 2 ? i : 1 ;
				hotkeys[key][keys_analyze[j]] = 1 ;
			}
		}

		$(ele).bind("keydown", function(evt){
			if(!Drunk.isUndef(keys_mustdown[evt.which])){
				keys_mustdown[evt.which]["down"] = true ;
			}else if(!Drunk.isUndef(hotkeys[evt.which])){
				var keycode = evt.which , i , HOTKEY ;
				event.keyCode = 0 ;
				// 如果热键记录值不为0,即为组合热键,则遍历组合状态键,如果其为该热键的成员状态键,且非按下状态,则还原返回键值
				if(hotkeys[keycode])for(i in hotkeys[keycode]){if(!keys_mustdown[i]["down"]){event.keyCode = keycode;return evt;}}
				if(!event.keyCode && (HOTKEY = keys_mustdown[i] ? i : keycode) && $.isFunction(config[HOTKEY])){
					config[HOTKEY]() ;
					event.keyCode = keycode ;
				}
				return isBubble ? evt : false ;
			}
		}).bind("keyup", function(evt){
			if(!Drunk.isUndef(keys_mustdown[evt.which])){
				keys_mustdown[evt.which]["down"] = false ;
			}
		}) ;
	} ,
	
	time : function(time, method){
		method = method || 0 ;
		var time = (time ? Drunk.parseISO8601(time) : new Date()).getTime() ;
		return method & 1 ? time : Math.ceil(time / 1000) ;
	} ,

    parseISO8601 : function(s) {
        var regexDate = /^\s*(\d{2,4})-(\d{1,2})-(\d{1,2})/,
            regexTime = /(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?\s*$/,
            substr = function(str, from, len){ return str.substr((from < 0 ? str.length : 0) + from, len)};
        if(regexDate.test(s)) s = s.replace(regexDate, function($0,$1,$2,$3){ return $1 +'-'+ substr('0'+$2, -2) +'-'+ substr('0'+$3, -2) });
        if(regexTime.test(s)) s = s.replace(regexTime, function($0,$1,$2,$3){ return $1 +':'+ substr('0'+$2, -2) +':'+ substr('0'+$3, -2) });
        var regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:(?:T|\s)(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,}))?(Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/,
            m = regexIso8601.exec(s);
        if(m && D.browser.msie){
            var lOff = -(new Date().getTimezoneOffset()),
                lHrs = Math.floor(lOff / 60),
                lMin = lOff % 60;
            s = Date.UTC(
                m[1],
                (m[2] || 1) - 1,
                m[3] || 1,
                m[4] - (m[8] ? m[9] ? m[9] + m[10] : 0 : lHrs) || 0,
                m[5] - (m[8] ? m[9] ? m[9] + m[11] : 0 : lMin) || 0,
                m[6] || 0,
                ((m[7] || 0) + '00').substr(0, 3)
            );
        }
        return new Date(s);
    },

    date : function(format,timestamp){
		var that = this, jsdate, f,
		txt_words = ["Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
		formatChr = /\\?(.?)/gi,
		formatChrCb = function (t, s) {return f[t] ? f[t]() : s;},
		_pad = function (n, c) {
			n = String(n);
			while (n.length < c)n = '0' + n;
			return n;
		};
		
		f = {
			d: function () {return _pad(f.j(), 2);},
			D: function () {return f.l().slice(0, 3);},
			j: function () {return jsdate.getDate();},
			l: function () {return txt_words[f.w()] + 'day';},
			N: function () {return f.w() || 7;},
			S: function(){
				var j = f.j(),
				i = j%10;
				if (i <= 3 && parseInt((j%100)/10, 10) == 1) {i = 0;}
				return ['st', 'nd', 'rd'][i - 1] || 'th';
			},
			w: function () {return jsdate.getDay();},
			z: function () {
				var a = new Date(f.Y(), f.n() - 1, f.j()),
				b = new Date(f.Y(), 0, 1);
				return Math.round((a - b) / 864e5);
			},

			W: function () {
				var a = new Date(f.Y(), f.n() - 1, f.j() - f.N() + 3),
					b = new Date(a.getFullYear(), 0, 4);
				return _pad(1 + Math.round((a - b) / 864e5 / 7), 2);
			},

			F: function () {return txt_words[6 + f.n()];},
			m: function () {return _pad(f.n(), 2);},
			M: function () {return f.F().slice(0, 3);},
			n: function () {return jsdate.getMonth() + 1;},
			t: function () {return (new Date(f.Y(), f.n(), 0)).getDate();},

			L: function () {
				var j = f.Y();
				return j % 4 === 0 & j % 100 !== 0 | j % 400 === 0;
			},
			o: function () {
				var n = f.n(),
					W = f.W(),
					Y = f.Y();
				return Y + (n === 12 && W < 9 ? 1 : n === 1 && W > 9 ? -1 : 0);
			},
			Y: function () {return jsdate.getFullYear();},
			y: function () {return f.Y().toString().slice(-2);},

			a: function () {return jsdate.getHours() > 11 ? "pm" : "am";},
			A: function () {return f.a().toUpperCase();},
			B: function () {
				var H = jsdate.getUTCHours() * 36e2,
					i = jsdate.getUTCMinutes() * 60,
					s = jsdate.getUTCSeconds();
				return _pad(Math.floor((H + i + s + 36e2) / 86.4) % 1e3, 3);
			},
			g: function () {return f.G() % 12 || 12;},
			G: function () {return jsdate.getHours();},
			h: function () {return _pad(f.g(), 2);},
			H: function () {return _pad(f.G(), 2);},
			i: function () {return _pad(jsdate.getMinutes(), 2);},
			s: function () {return _pad(jsdate.getSeconds(), 2);},
			u: function () {return _pad(jsdate.getMilliseconds() * 1000, 6);},

			e: function () {throw 'Not supported (see source code of date() for timezone on how to add support)';},
			I: function () {
				var a = new Date(f.Y(), 0),
				c = Date.UTC(f.Y(), 0),
				b = new Date(f.Y(), 6),
				d = Date.UTC(f.Y(), 6);
				return ((a - c) !== (b - d)) ? 1 : 0;
			},
			O: function () {
				var tzo = jsdate.getTimezoneOffset(),
					a = Math.abs(tzo);
				return (tzo > 0 ? "-" : "+") + _pad(Math.floor(a / 60) * 100 + a % 60, 4);
			},
			P: function () {
				var O = f.O();
				return (O.substr(0, 3) + ":" + O.substr(3, 2));
			},
			T: function () {return 'UTC';},
			Z: function () {return -jsdate.getTimezoneOffset() * 60;},

			c: function () {return 'Y-m-d\TH:i:sP'.replace(formatChr, formatChrCb);},
			r: function () {return 'D, d M Y H:i:s O'.replace(formatChr, formatChrCb);},
			U: function () {return jsdate / 1000 | 0;}
		};
		this.date = function (format, timestamp) {
			that = this;
			jsdate = (timestamp === undefined ? new Date() : (timestamp instanceof Date) ? new Date(timestamp) : new Date(timestamp * 1000));
			return format.replace(formatChr, formatChrCb);
		};
		return this.date(format, timestamp);
	},

    date_empty : function(val){
        if(Drunk.empty(val)) return 1;
        return /^00(?:00)?\b/.test(val);
    }
}) ;